package com.yw.service.Impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.yw.interfaceManageInfo.dto.*;
import com.yw.interfaceManageInfo.domain.InterfaceManageInfo;
import com.yw.interfaceManageInfo.vo.InterfaceManageInfoVO;
import com.yw.interfaceManageInfo.vo.QueryTestVO;
import com.yw.interfaceManageInfo.vo.TaskInterfaceVO;
import com.yw.interfaceManageInfo.vo.TaskValuesVO;
import com.yw.mapper.InterfaceMapper;
import com.yw.piliangDTO.StatusDTO;
import com.yw.result.PageDTO;
import com.yw.result.R;
import com.yw.service.InterfaceService;
import com.yw.utils.BeanConverter;
import jakarta.annotation.Resource;
import net.bytebuddy.description.method.MethodDescription;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;


import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.*;

@Service
public class InterfaceServiceImpl extends ServiceImpl<InterfaceMapper, InterfaceManageInfo>
                                implements InterfaceService {

    @Resource
    private InterfaceMapper interfaceMapper;

    @Resource
    private RestTemplate restTemplate;

    @Resource
    private ObjectMapper objectMapper;
    @Override
    public Boolean updateStatic(Integer id) {
        InterfaceManageInfo interfaceManageInfo = interfaceMapper.selectById(id);
        switch (interfaceManageInfo.getApiState()){
            case 0, 2:
                interfaceManageInfo.setApiState(1);break;
            case 1:
                interfaceManageInfo.setApiState(2);break;
        }
         if(interfaceMapper.updateById(interfaceManageInfo) !=0){
             return true;
         }else {
             return false;
         }
    }

    @Override
    public Page<InterfaceManageInfoVO> pageByCondition(ConditionPageDTO conditionPageDTO) {
            LambdaQueryWrapper<InterfaceManageInfo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(conditionPageDTO.getSource() !=null,InterfaceManageInfo::getSource, conditionPageDTO.getSource())
                    .eq(conditionPageDTO.getApiState() != null,InterfaceManageInfo::getApiState, conditionPageDTO.getApiState())
                    .like(conditionPageDTO.getInterfaceName() !=null,InterfaceManageInfo::getInterfaceName, conditionPageDTO.getInterfaceName());
            Page<InterfaceManageInfo> interfacePage = new Page<>(conditionPageDTO.getPageNumber(), conditionPageDTO.getPageSize());
            Page<InterfaceManageInfo> page = this.page(interfacePage, wrapper);
            Page<InterfaceManageInfoVO> infoVOPage = new Page<>();
            infoVOPage.setRecords(BeanConverter.convertList(page.getRecords(), InterfaceManageInfoVO.class));
            infoVOPage.setTotal(page.getTotal());
            infoVOPage.setCurrent(page.getCurrent());
            infoVOPage.setSize(page.getSize());
            return infoVOPage;
        }

    @Override
    public Page<InterfaceManageInfoVO> pageListVO(PageDTO pageDTO) {
        Page<InterfaceManageInfo> interfacePage = new Page<>(pageDTO.getPageNumber(), pageDTO.getPageSize());
        Page<InterfaceManageInfo> page = this.page(interfacePage);
        Page<InterfaceManageInfoVO> infoVOPage = new Page<>();
        infoVOPage.setRecords(BeanConverter.convertList(page.getRecords(),InterfaceManageInfoVO.class));
        infoVOPage.setTotal(page.getTotal());
        infoVOPage.setCurrent(page.getCurrent());
        infoVOPage.setSize(page.getSize());
        return infoVOPage;

    }

    //保存接口
    @Override
    public Boolean saveInterface(InterfaceManageInfoDTO interfaceManageInfoDTO) {
        InterfaceManageInfo newInterface = new InterfaceManageInfo();
        newInterface.setInterfaceType(interfaceManageInfoDTO.getInterfaceType());
        newInterface.setInterfaceName(interfaceManageInfoDTO.getInterfaceName());
        newInterface.setSource(interfaceManageInfoDTO.getSource());
        newInterface.setInterfaceDesc(interfaceManageInfoDTO.getInterfaceDesc());
        newInterface.setAgreement(interfaceManageInfoDTO.getAgreement());
        newInterface.setApiState(interfaceManageInfoDTO.getApiState());
        newInterface.setIp(interfaceManageInfoDTO.getIp());
        newInterface.setPath(interfaceManageInfoDTO.getPath());
        newInterface.setRequestMethod(interfaceManageInfoDTO.getRequestMethod());
        newInterface.setTimeout(interfaceManageInfoDTO.getTimeout());
        newInterface.setInValue(JSONUtil.toJsonStr(interfaceManageInfoDTO.getInValues()));
        newInterface.setOutValue(JSONUtil.toJsonStr(interfaceManageInfoDTO.getOutValue()));
        newInterface.setRequestBody(JSONUtil.toJsonStr(interfaceManageInfoDTO.getRequestBody()));
        newInterface.setUpdateTime(LocalDateTime.now());
        newInterface.setCreateTime(LocalDateTime.now());
        if(this.save(newInterface)){
            return true;
        }else {
            return false;
        }
    }

    @Override
    public InterfaceManageInfoDTO oneInterface(Integer id) {
        InterfaceManageInfoDTO interfaceManageInfoDTO = new InterfaceManageInfoDTO();
        InterfaceManageInfo one = this.getById(id);
        interfaceManageInfoDTO.setId(one.getId());
        interfaceManageInfoDTO.setInterfaceName(one.getInterfaceName());
        interfaceManageInfoDTO.setInterfaceType(one.getInterfaceType());
        interfaceManageInfoDTO.setInterfaceDesc(one.getInterfaceDesc());
        interfaceManageInfoDTO.setIp(one.getIp());
        interfaceManageInfoDTO.setAgreement(one.getAgreement());
        interfaceManageInfoDTO.setPath(one.getPath());
        interfaceManageInfoDTO.setSource(one.getSource());
        interfaceManageInfoDTO.setApiState(one.getApiState());
        interfaceManageInfoDTO.setRequestMethod(one.getRequestMethod());
        interfaceManageInfoDTO.setTimeout(one.getTimeout());
        try {
            interfaceManageInfoDTO.setInValues(objectMapper.readValue(one.getInValue(), new TypeReference<List<InValueDTO>>() {}));
            interfaceManageInfoDTO.setOutValue(objectMapper.readValue(one.getOutValue(), new TypeReference<List<OutValueDTO>>() {}));
            interfaceManageInfoDTO.setRequestBody(objectMapper.readValue(one.getRequestBody(), new TypeReference<List<BodyDTO>>() {}));
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        return interfaceManageInfoDTO;
    }

    @Override
    public Boolean updateInterface(InterfaceManageInfoDTO interfaceManageInfoDTO) {
        InterfaceManageInfo newInterface = new InterfaceManageInfo();
        InterfaceManageInfo one = this.getById(interfaceManageInfoDTO.getId());
        newInterface.setInterfaceType(interfaceManageInfoDTO.getInterfaceType());
        newInterface.setInterfaceName(interfaceManageInfoDTO.getInterfaceName());
        newInterface.setSource(interfaceManageInfoDTO.getSource());
        newInterface.setInterfaceDesc(interfaceManageInfoDTO.getInterfaceDesc());
        newInterface.setAgreement(interfaceManageInfoDTO.getAgreement());
        newInterface.setApiState(interfaceManageInfoDTO.getApiState());
        newInterface.setIp(interfaceManageInfoDTO.getIp());
        newInterface.setPath(interfaceManageInfoDTO.getPath());
        newInterface.setRequestMethod(interfaceManageInfoDTO.getRequestMethod());
        newInterface.setTimeout(interfaceManageInfoDTO.getTimeout());
        newInterface.setInValue(JSONUtil.toJsonStr(interfaceManageInfoDTO.getInValues()));
        newInterface.setOutValue(JSONUtil.toJsonStr(interfaceManageInfoDTO.getOutValue()));
        newInterface.setRequestBody(JSONUtil.toJsonStr(interfaceManageInfoDTO.getRequestBody()));
        newInterface.setUpdateTime(LocalDateTime.now());
        newInterface.setCreateTime(one.getCreateTime());
        if(this.save(newInterface)){
            return true;
        }else {
            return false;
        }
    }


//批量发布或停用
@Override
public Boolean batch(StatusDTO statusDTO) {
    return interfaceMapper.batch(statusDTO);
}

//    批量修改类型
    @Override
    public Boolean updateTypeBatch(List<Integer> ids, String type) {
        return interfaceMapper.updateTypeBatch(ids,type);
    }

    @Override
    public R test(TestDTO testDTO) {
        switch (testDTO.getAgreement()){
            case "GET":
//                调用自己定义的拼接字符串方法得到完整的get请求的url，再调用自己定义的getExample方法实现远程调用
                return this.getExample(this.montageURL(testDTO.getMap(),testDTO.getRequestURL(),true));
            case "POST":
                return this.postExample(this.montageURL(testDTO.getMap(),testDTO.getRequestURL(),false),testDTO.getMap());
            case "PUT":break;
            case "DELETE":break;
        }
        return null;
    }

//    get请求
    public R getExample(String url) {
        R response = null;
        try {
            response = restTemplate.getForObject(url, R.class);
            System.out.println(response);
            return response;
        } catch (RestClientException e) {
            throw new RuntimeException(e);
        }

    }

//post请求
    public R postExample(String url,Map<String,Object> map) {
        R response = null;
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON); // 设置请求头为 JSON 格式
        HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(map, headers);
        try {
            Map<String, String> urlParams = new HashMap<>();
                response = restTemplate.postForObject(url,requestEntity, R.class, urlParams);
            System.out.println(response);
            return response;
        } catch (RestClientException e) {
            throw new RuntimeException(e);
        }

    }

    @Override
//    查询接口测试详情
    public QueryTestVO testDetails(Integer id){
        InterfaceManageInfo oneInterface = this.getById(id);
        String requestMethod = oneInterface.getRequestMethod();
        String ip = oneInterface.getIp();
        String path = oneInterface.getPath();
        String agreement = oneInterface.getAgreement().toLowerCase();
        String urlBase = agreement + "://" + ip + path;
        QueryTestVO queryTestVO = new QueryTestVO();
        queryTestVO.setRequestURL(urlBase);
        queryTestVO.setAgreement(requestMethod);
        try {
            queryTestVO.setInValues(objectMapper.readTree(oneInterface.getInValue()));//转换为json返回给前端
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        return queryTestVO;
    }

    @Override
    public List<TaskInterfaceVO> taskGetInterface() {
        List<InterfaceManageInfo> list = this.list();
        ArrayList<TaskInterfaceVO> taskInterfaceVOS = new ArrayList<>();
        for (InterfaceManageInfo interfaceManageInfo : list) {
            TaskInterfaceVO taskInterfaceVO = new TaskInterfaceVO();
            taskInterfaceVO.setId(interfaceManageInfo.getId());
            taskInterfaceVO.setInterFaceName(interfaceManageInfo.getInterfaceName());
            taskInterfaceVOS.add(taskInterfaceVO);
        }
        return taskInterfaceVOS;
    }

    @Override
    public TaskValuesVO getValues(Integer id) {
        InterfaceManageInfo one = this.getById(id);
        TaskValuesVO taskValuesVO = new TaskValuesVO();
        taskValuesVO.setId(id);
        taskValuesVO.setApiName(one.getInterfaceName());
        try {
            taskValuesVO.setInValueDTOS(new ObjectMapper().readTree(one.getInValue()));
            taskValuesVO.setOutValueDTOS(new ObjectMapper().readTree(one.getOutValue()));
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        return taskValuesVO;
    }



    //拼接完整url
    public String montageURL(Map<String,Object> map,String urlBase,Boolean a){
            //拼接查询参数
        if(a){
            StringBuilder queryString = new StringBuilder();
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                if (queryString.length() > 0) {
                    queryString.append("&");
                }
                try {
                    String encodedKey = URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8.toString());
                    String encodedValue = URLEncoder.encode(entry.getValue().toString(), StandardCharsets.UTF_8.toString());
                    queryString.append(encodedKey).append("=").append(encodedValue);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            //拼接完整url
            String url = urlBase + "?" + queryString.toString();
            System.out.println("url=" + url);
            return url;
        }else {
            return urlBase;
        }
    }
}
